import {
  Renderer2,
  Component,
  OnInit,
  AfterContentInit,
  Input,
  ContentChildren,
  QueryList,
  ViewChild,
  EventEmitter,
  ElementRef,
  Output} from '@angular/core';
import { HCarouselContentDirective, EventFn } from '../h-carousel-content.directive';

@Component({
  selector: 'app-h-carousel',
  templateUrl: './h-carousel.component.html',
  styleUrls: ['./h-carousel.component.less']
})
export class HCarouselComponent implements OnInit , AfterContentInit {
  @ViewChild('carousel') eleCarousel: ElementRef;
  @ViewChild('content') content: ElementRef;
  @ContentChildren(HCarouselContentDirective) items: QueryList <HCarouselContentDirective>;
  private minW: number;
  private maxW: number = 0;
  private itemW: number;
  private currentIndex: number = 0;
  private _startPosition = {
    left: 0,
    top: 0
  };
  private _currentPosition = {
    left: 0,
    top: 0
  };
  @Input()
  set current (value: number) {
    this.currentIndex = value;
  }
  @Output() change: EventEmitter<any> = new EventEmitter();
  // 切换哨兵
  get sentry () {
      return 60;
  }
  // 激活状态类名
  get activeClass() {
    return 'active';
  }
  constructor(private randerer: Renderer2) { }

  ngOnInit() {}

  ngAfterContentInit() {
    this.setContentStyle();
    this.renderContent();
    this.setActive();
    this.goTo(this.currentIndex);
  }

  renderContent() {
    const _this = this;
    this.items.forEach((item: HCarouselContentDirective) => {

      item.moveFn = _this.touchMove;
      item.startFn = _this.touchStart;
      item.endFn = _this.touchEnd;
      item.style = {
        flex: `0 0 ${this.itemW}px`,
        width: `${this.itemW}px`,
      };
    });
  }

  setContentStyle() {
    const carousel = this.eleCarousel.nativeElement;
    const content = this.content.nativeElement;
    const width = carousel.offsetWidth;
    if (this.items.length) {
      this.minW = (this.items.length - 1) * width * -1;
      this.itemW = width;
      this.randerer.setStyle(content, 'width', `${this.items.length * width}px`);
      this.randerer.setStyle(content, 'transform', `translateX(0px)`);
    }
  }

  touchStart: EventFn = (data) => {
    this.setTransition();
    this._startPosition = {
        left: data.clientX,
        top: data.clientY
    };
  }

  touchMove: EventFn = (data) => {
    const { clientX } = data;
    let left = clientX - this._startPosition.left;
    left  = this.inSection(this._currentPosition.left + left);
    this.randerer.setStyle(this.content.nativeElement, 'transform', `translateX(${left}px)`);
  }

  touchEnd: EventFn = (data) => {
    const left = data.clientX - this._startPosition.left;
    let currentIndex = this.currentIndex;
    if (Math.abs(left) > this.sentry) {
      // 判断方向
      const index = left > 0 ? -1 : 1 ;
      currentIndex = this.inIndex(this.currentIndex + index);
    }

    this.goTo(currentIndex);
  }

  goTo (index: number) {
    index = this.inIndex(index);
    const left = this.inSection(this.itemW * index * -1);
    this.currentIndex = index;
    this.setTransition(true);
    this._currentPosition = {
      left,
      top: 0
    };
    this.setActive(index);
    this.change.emit(index);
    this.randerer.setStyle(this.content.nativeElement, 'transform', `translateX(${left}px)`);
  }

  // 设置过渡
  setTransition(has = false) {
    const style = has ? 'all .4s' : '';
    this.randerer.setStyle(this.content.nativeElement, 'transition', style);
  }

  // 限制编号
  inIndex(index: number) {
    if (index < 0) {
      index = 0;
    } else if (index >= this.items.length) {
      index = this.items.length - 1;
    }
    return index;
  }
  // 限制区间
  inSection(data: number): number {
    if ( data  < this.minW ) {
      return this.minW;
    }
    if (data > this.maxW ) {
      return this.maxW;
    }
    return data;
  }

  // 设置选中项类
  setActive(current = this.currentIndex) {
    this.items.forEach((item, index) => {
      item.isActive = index === current;
    });

  }

}
